@file:Suppress("FunctionName", "unused")

package dev.entao.page

import dev.entao.base.*
import dev.entao.core.OnHttpContext
import dev.entao.sql.*
import kotlin.reflect.full.hasAnnotation

private inline fun <R> String.ifNotEmpty(block: (String) -> R): R? {
    return if (this.isEmpty()) null else block(this)
}

//TODO bool
context (OnHttpContext)
val Prop.contextValue: Any?
    get() {
        return when (this.returnClass) {
            Int::class -> context[this]?.toIntOrNull()
            Long::class -> context[this]?.toLongOrNull()
            Float::class, Double::class -> context[this]?.toDoubleOrNull()
            String::class -> {
                val s = context[this] ?: return null
                if (s.isNotEmpty()) {
                    return s
                } else null
            }
            else -> null
        }
    }

context(OnHttpContext)
fun Model.fillProps(vararg ps: Prop) {
    fromRequest(ps.map { it.userName }.toSet())
}

context(OnHttpContext)
fun Model.fromRequest(keySet: Set<String> = emptySet()) {
    val nameSet = context.paramMap.keys
    val thisModel = this
    thisModel::class._SQLProperties.forEach {
        val key = it.userName
        val b = if (keySet.isNotEmpty()) {
            key in nameSet && key in keySet
        } else {
            key in nameSet
        }
        if (b) {
            val sval = context[key]
            if (sval != null) {
                val v: String = if (it.hasAnnotation<Trim>()) {
                    sval.trim()
                } else {
                    sval
                }
                it.setPropValue(thisModel, it.decodeAndCast(v))
            }
        }
    }
}

context (OnHttpContext)
fun equalProps(vararg ps: Prop): Where? {
    return ps.fold(null) { w: Where?, p: Prop ->
        w AND p.EQ()
    }

}

context(OnHttpContext)
fun EQS(vararg ps: Prop): Where? {
    return ps.fold(null) { w: Where?, p ->
        w AND p.EQ()
    }
}

context (OnHttpContext)
fun Prop.EQ(): Where? {
    val v = this.contextValue ?: return null
    return this EQ v
}

// %value%
context(OnHttpContext)
fun Prop1.LIKE_IN(): Where? {
    val v = this.contextValue ?: return null
    if (v.toString().isEmpty()) {
        return null
    }
    return this LIKE """%$v%"""
}

// value%
context(OnHttpContext)
fun Prop1.LIKE_(): Where? {
    val v = this.contextValue ?: return null
    if (v.toString().isEmpty()) {
        return null
    }
    return this LIKE """$v%"""
}

// %value
context(OnHttpContext)
fun Prop1._LIKE(): Where? {
    val v = this.contextValue ?: return null
    if (v.toString().isEmpty()) {
        return null
    }
    return this LIKE """%$v"""
}

context(OnHttpContext)
fun Prop1.NE(): Where? {
    val v = this.contextValue ?: return null
    return this NE v
}

context(OnHttpContext)
fun Prop1.GE(): Where? {
    val v = this.contextValue ?: return null
    return this GE v
}

context(OnHttpContext)
fun Prop1.GT(): Where? {
    val v = this.contextValue ?: return null
    return this GT v
}

context(OnHttpContext)
fun Prop1.LE(): Where? {
    val v = this.contextValue ?: return null
    return this LE v
}

context(OnHttpContext)
fun Prop1.LT(): Where? {
    val v = this.contextValue ?: return null
    return this LT v
}




